package com.golte.utils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;

import org.springframework.util.StringUtils;

/**
 * @author hegd
 * @version V1.0
 * @description: 日期时间工具类
 * @date 2021-06-03
 */

public class DateUtils {

    /**
     * 默认日期时间格式
     */
    public static final String DATE_TIME_PATTERN_DEFAULT = "yyyy-MM-dd HH:mm:ss";
    /**
     * 数字日期时间格式
     */
    public static final String DATE_TIME_PATTERN_NUMBER = "yyyyMMddHHmmss";
    /**
     * 默认日期格式
     */
    public static final String DATE_PATTERN_DEFAULT = "yyyy-MM-dd";
    /**
     * 日期格式yyyy-mm
     */
    public static final String DATE_PATTERN_YM = "yyyy-MM";
    /**
     * 数字日期时间格式 yyyyMMdd
     */
    public static final String DATE_PATTERN_NUMBER = "yyyyMMdd";
    /**
     * 数字日期时间格式 yyyyMMddHH
     */
    public static final String DATE_PATTERN_NUMBER_HOUR = "yyyyMMddHH";
    /**
     * 一天的开始时间
     */
    public static final String START_TIME_OF_DAY = "00:00:00";
    /**
     * 一天的结束时间
     */
    public static final String END_TIME_OF_DAY = "23:59:59";
    /**
     * 一天毫秒数
     */
    public static final long ONE_DAY_MILLISECOND = 24 * 60 * 60 * 1000;
    /**
     * 一小时毫秒数
     */
    public static final long ONE_HOUR_MILLISECOND = 60 * 60 * 1000;
    /**
     * 一分钟毫秒数
     */
    public static final long ONE_MINUTE_MILLISECOND = 60 * 1000;


    /**
     * <h2>将时间按照 patten 转成对应格式的 String</h2>
     *
     * @param pattern  {@link String} 时间格式
     * @param temporal {@link TemporalAccessor} 要转换的时间对象
     * @return 转换后的时间字符串
     */
    public static String dateTime2Str(String pattern, TemporalAccessor temporal) {
        if (StringUtils.isEmpty(pattern) || temporal == null) {
            return null;
        }
        return DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault()).format(temporal);
    }

    /**
     * <h2>将系统时间按照 patten 转成对应格式的 String</h2>
     *
     * @param pattern {@link String} 时间格式
     * @return 转换后的时间字符串
     */
    public static String dateTime2Str(String pattern) {
        if (StringUtils.isEmpty(pattern)) {
            return null;
        }
        return dateTime2Str(pattern, LocalDateTime.now());
    }

    /**
     * <h2>将时间转成对应格式的 String</h2>
     *
     * @param date {@link Date} 时间
     * @return 转换后的时间字符串
     */
    public static String dateTime2Str(Date date) {
        return dateTime2Str(DATE_TIME_PATTERN_DEFAULT, date);
    }

    /**
     * <h2>将系统时间按照 默认格式 转成对应 String</h2>
     *
     * @return 转换后的时间字符串
     */
    public static String dateTime2Str() {
        return dateTime2Str(DATE_TIME_PATTERN_DEFAULT, LocalDateTime.now());
    }

    /**
     * <h2>将系统时间按照 默认格式 转成对应 String</h2>
     *
     * @return 转换后的时间字符串
     */
    public static String dateYmd2Str() {
        return dateTime2Str(DATE_PATTERN_NUMBER, LocalDateTime.now());
    }

    /**
     * <h2>将系统时间按照 默认格式 转成对应 String</h2>
     *
     * @return 转换后的时间字符串
     */
    public static String dateYmdH2Str() {
        return dateTime2Str(DATE_PATTERN_NUMBER_HOUR, LocalDateTime.now());
    }

    /**
     * <h2>将时间按照 patten 转成对应格式的 String</h2>
     *
     * @param pattern {@link String} 时间格式
     * @param date    {@link Date} 时间
     * @return 转换后的时间字符串
     */
    public static String dateTime2Str(String pattern, Date date) {
        if (StringUtils.isEmpty(pattern) || date == null) {
            return null;
        }
        return DateTimeFormatter.ofPattern(pattern).format(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
    }


    /**
     * <h2>将字符串按照 patten 转成 Date</h2>
     *
     * @param pattern {@link String} 时间格式
     * @param dateStr {@link String} 要转换的字符串
     * @return 转换后的时间
     */
    public static Date str2Date(String pattern, String dateStr) {
        if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(dateStr)) {
            return null;
        }
        return Date.from(LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern)).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * <h2>将字符串按照 patten 转成 Date</h2>
     *
     * @param dateStr {@link String} 要转换的字符串
     * @return 转换后的时间
     */
    public static Date str2Date(String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        return Date.from(LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(DATE_TIME_PATTERN_DEFAULT)).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * <h2>获取前一天时间</h2>
     *
     * @return 转换后的时间字符串
     */
    public static String getYesterdayByFormat() {
        return LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN_DEFAULT));
    }

    /**
     * <h2>获取当前时间+/-day的时间</h2>
     *
     * @param day -1 or 1
     * @return 转换后的时间字符串
     */
    public static Date getNowPlusDays(long day) {
        return Date.from(LocalDateTime.now().plusDays(day).atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * <h2>计算相差时间 天 时 分</h2>
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return day + "天" + hour + "时"+ minute + "分"
     */
    public static String getDatePoor(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            return null;
        }
        long diff = endDate.getTime() - startDate.getTime();
        long day = diff / ONE_DAY_MILLISECOND;
        long hour = diff % ONE_DAY_MILLISECOND / ONE_HOUR_MILLISECOND;
        long minute = diff % ONE_DAY_MILLISECOND % ONE_HOUR_MILLISECOND / ONE_MINUTE_MILLISECOND;
        return day + "天" + hour + "时" + minute + "分";
    }

    /**
     * <h2>计算相差时间 小时/h2>
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return hour + "时"
     */
    public static Long getHours(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            return null;
        }
        long diff = endDate.getTime() - startDate.getTime();

        long hour = diff % ONE_DAY_MILLISECOND / ONE_HOUR_MILLISECOND;

        return hour ;
    }


    /**
     * <h2>获取long月前的时间</h2>
     *
     * @param num 1
     * @return 转换后的时间字符串
     */
    public static String getMinusMonths(long num) {
        return LocalDateTime.now().minusMonths(num).format(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN_DEFAULT));
    }


    public static void main(String[] args) {
        String localDateTime = LocalDateTime.now().minusMonths(1).format(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN_DEFAULT));
        System.out.println(localDateTime);
    }
}
